package de.easywakeup.yahooWeather;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.os.AsyncTask;
import de.easywakeup.data.Data;

public class GetWeather
{

	private static Data data;

	public void startQuery( String woeid )
	{
		new MyQueryYahooWeatherTask( ).execute( );
	}

	public GetWeather( )
	{
		data = Data.singleton( );
		Data.setGetWeather( this );
	}

	private static class MyQueryYahooWeatherTask extends AsyncTask< Void, Void, Void >
	{
		String weatherString;

		@Override
		protected Void doInBackground( Void... arg0 )
		{
			weatherString = QueryYahooWeather( );
			Document weatherDoc = convertStringToDocument( weatherString );

			if( weatherDoc != null )
			{
				parseWeather( weatherDoc );
			}
			else
			{
				System.out.println( "Cannot convertStringToDocument!" );
			}

			return null;
		}

		@Override
		protected void onPostExecute( Void result )
		{
			// Update the GUI here

			// weather.setText(weatherResult);
			super.onPostExecute( result );
		}

		private String QueryYahooWeather( )
		{
			String qResult = "";
			// The optional u (units) parameter indicates the degree units for
			// the weather forecast. By default, Yahoo! Weather returns
			// temperature information in degrees Fahrenheit. Use the u
			// parameter to explicitly specify the degree units in Fahrenheit
			// (f) or Celsius (c). The units parameter is case sensitive. For
			// example, to get the weather forecast in Sunnyvale, CA in Celsius:
			String queryString = "http://weather.yahooapis.com/forecastrss?w=" + data.getWoeid( ) + "&u=c";

			HttpClient httpClient = new DefaultHttpClient( );
			HttpGet httpGet = new HttpGet( queryString );

			try
			{
				HttpEntity httpEntity = httpClient.execute( httpGet ).getEntity( );

				if( httpEntity != null )
				{
					InputStream inputStream = httpEntity.getContent( );
					Reader in = new InputStreamReader( inputStream );
					BufferedReader bufferedreader = new BufferedReader( in );
					StringBuilder stringBuilder = new StringBuilder( );

					String stringReadLine = null;

					while( ( stringReadLine = bufferedreader.readLine( ) ) != null )
					{
						stringBuilder.append( stringReadLine + "\n" );
					}

					qResult = stringBuilder.toString( );
				}
			}
			catch( ClientProtocolException e )
			{
				e.printStackTrace( );
			}
			catch( IOException e )
			{
				e.printStackTrace( );
			}
			return qResult;
		}

		private Document convertStringToDocument( String src )
		{
			Document dest = null;

			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance( );
			DocumentBuilder parser;

			try
			{
				// Parse the xml to validated data
				parser = dbFactory.newDocumentBuilder( );
				dest = parser.parse( new ByteArrayInputStream( src.getBytes( ) ) );
			}
			catch( ParserConfigurationException e1 )
			{
				e1.printStackTrace( );
			}
			catch( SAXException e )
			{
				e.printStackTrace( );
			}
			catch( IOException e )
			{
				e.printStackTrace( );
			}

			return dest;
		}

		private void parseWeather( Document srcDoc )
		{

			// <description>Yahoo! Weather for New York, NY</description>
			NodeList descNodelist = srcDoc.getElementsByTagName( "description" );
			if( descNodelist != null && descNodelist.getLength( ) > 0 )
			{
				data.setDescription( descNodelist.item( 0 ).getTextContent( ) );
			}
			else
			{
				data.setDescription( "EMPTY" );
			}

			// <yweather:location city="New York" region="NY"
			// country="United States"/>
			NodeList locationNodeList = srcDoc.getElementsByTagName( "yweather:location" );
			if( locationNodeList != null && locationNodeList.getLength( ) > 0 )
			{
				Node locationNode = locationNodeList.item( 0 );
				NamedNodeMap locNamedNodeMap = locationNode.getAttributes( );

				data.setCity( locNamedNodeMap.getNamedItem( "city" ).getNodeValue( ).toString( ) );
				data.setRegion( locNamedNodeMap.getNamedItem( "region" ).getNodeValue( ).toString( ) );
				data.setCountry( locNamedNodeMap.getNamedItem( "country" ).getNodeValue( ).toString( ) );
			}
			else
			{
				data.setCity( "EMPTY" );
				data.setRegion( "EMPTY" );
				data.setCountry( "EMPTY" );
			}

			// <yweather:wind chill="60" direction="0" speed="0"/>
			NodeList windNodeList = srcDoc.getElementsByTagName( "yweather:wind" );
			if( windNodeList != null && windNodeList.getLength( ) > 0 )
			{
				Node windNode = windNodeList.item( 0 );
				NamedNodeMap windNamedNodeMap = windNode.getAttributes( );

				data.setWindChill( windNamedNodeMap.getNamedItem( "chill" ).getNodeValue( ).toString( ) );
				data.setWindDirection( windNamedNodeMap.getNamedItem( "direction" ).getNodeValue( ).toString( ) );
				data.setWindSpeed( windNamedNodeMap.getNamedItem( "speed" ).getNodeValue( ).toString( ) );
			}
			else
			{
				data.setWindChill( "EMPTY" );
				data.setWindDirection( "EMPTY" );
				data.setWindSpeed( "EMPTY" );
			}

			// <yweather:atmosphere humidity="40" visibility="9.99"
			// pressure="1015.92" rising="2"/>
			NodeList atmosphereNodeList = srcDoc.getElementsByTagName( "yweather:atmosphere" );
			if( atmosphereNodeList != null && atmosphereNodeList.getLength( ) > 0 )
			{
				Node atmosphereNode = atmosphereNodeList.item( 0 );
				NamedNodeMap atmosphereNamedNodeMap = atmosphereNode.getAttributes( );

				data.setAtmosphereChill( atmosphereNamedNodeMap.getNamedItem( "humidity" ).getNodeValue( ).toString( ) );
				data.setAtmosphereVisibility( atmosphereNamedNodeMap.getNamedItem( "visibility" ).getNodeValue( ).toString( ) );
				data.setAtmospherePressure( atmosphereNamedNodeMap.getNamedItem( "pressure" ).getNodeValue( ).toString( ) );
				data.setAtmosphereRising( atmosphereNamedNodeMap.getNamedItem( "rising" ).getNodeValue( ).toString( ) );
			}
			else
			{
				data.setAtmosphereChill( "EMPTY" );
				data.setAtmosphereVisibility( "EMPTY" );
				data.setAtmospherePressure( "EMPTY" );
				data.setAtmosphereRising( "EMPTY" );
			}

			// <yweather:astronomy sunrise="6:52 am" sunset="7:10 pm"/>
			NodeList astNodeList = srcDoc.getElementsByTagName( "yweather:astronomy" );
			if( astNodeList != null && astNodeList.getLength( ) > 0 )
			{
				Node astNode = astNodeList.item( 0 );
				NamedNodeMap astNamedNodeMap = astNode.getAttributes( );

				data.setSunrise( astNamedNodeMap.getNamedItem( "sunrise" ).getNodeValue( ).toString( ) );
				data.setSunset( astNamedNodeMap.getNamedItem( "sunset" ).getNodeValue( ).toString( ) );
			}
			else
			{
				data.setSunrise( "EMPTY" );
				data.setSunset( "EMPTY" );
			}

			// <yweather:condition text="Fair" code="33" temp="60"
			// date="Fri, 23 Mar 2012 8:49 pm EDT"/>
			NodeList conditionNodeList = srcDoc.getElementsByTagName( "yweather:condition" );
			if( conditionNodeList != null && conditionNodeList.getLength( ) > 0 )
			{
				Node conditionNode = conditionNodeList.item( 0 );
				NamedNodeMap conditionNamedNodeMap = conditionNode.getAttributes( );
				data.setConditiontext( conditionNamedNodeMap.getNamedItem( "text" ).getNodeValue( ).toString( ) );
				data.setTemperature( conditionNamedNodeMap.getNamedItem( "temp" ).getNodeValue( ).toString( ) );
				data.setConditiondate( conditionNamedNodeMap.getNamedItem( "date" ).getNodeValue( ).toString( ) );
			}
			else
			{
				data.setConditiontext( "EMPTY" );
				data.setConditiondate( "EMPTY" );
			}
			System.out.println( "Temperatur: " + data.getTemperature( ) );

		}

	}

	public Data getData( )
	{
		return data;
	}

	public void setData( Data data )
	{
		GetWeather.data = data;
	}

}
